package org.springmvc.mybatis.handler;

import com.fasterxml.jackson.core.type.TypeReference;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.springmvc.json.JsonUtils;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Map;

/**
 * 将实体类中的Map<String, String>类型的属性持久化为json字符串到数据库对应字段
 * 并提供反序列化处理
 *
 * @author tangjialin on 2018-08-21.
 */
public class MapTypeHandler extends BaseTypeHandler<Map<String, Object>> {

    private static final TypeReference<Map<String, Object>> TYPE_REFERENCE = new TypeReference<Map<String, Object>>() {
    };

    /**
     * 数据存储时,将map转成json字符串
     *
     * @param ps        预编译SQL实例
     * @param i         参数的索引
     * @param parameter 参数值(即需要转成json字符串的map参数)
     * @param jdbcType  此参数指定的JDBC类型
     * @throws SQLException
     */
    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, Map<String, Object> parameter, JdbcType jdbcType) throws SQLException {
        ps.setString(i, JsonUtils.toJson(parameter));
    }

    /**
     * 查询数据时,将数据库存储的json字符串转成map对象
     *
     * @param rs         查询结果集实例对象
     * @param columnName 该值对应的字段名称
     * @return 返回转换后的值
     * @throws SQLException
     */
    @Override
    public Map<String, Object> getNullableResult(ResultSet rs, String columnName) throws SQLException {
        if (rs.wasNull()) { return null; }
        String value = rs.getString(columnName);
        if (value == null) { return null; }
        return JsonUtils.toObject(value, TYPE_REFERENCE);
    }

    /**
     * 查询数据时,将数据库存储的json字符串转成map对象
     *
     * @param rs          查询结果集实例对象
     * @param columnIndex 该值对应的字段索引
     * @return 返回转换后的值
     * @throws SQLException
     */
    @Override
    public Map<String, Object> getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        if (rs.wasNull()) { return null; }
        String value = rs.getString(columnIndex);
        if (value == null) { return null; }
        return JsonUtils.toObject(value, TYPE_REFERENCE);
    }

    /**
     * 查询数据时,将数据库存储的json字符串转成map对象
     *
     * @param cs          存储过程结果集实例对象
     * @param columnIndex 该值对应的字段索引
     * @return 返回转换后的值
     * @throws SQLException
     */
    @Override
    public Map<String, Object> getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        if (cs.wasNull()) { return null; }
        String value = cs.getString(columnIndex);
        if (value == null) { return null; }
        return JsonUtils.toObject(value, TYPE_REFERENCE);
    }
}
